package com.example.project.vo.model;

import cn.hutool.core.util.ObjUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.enums.SqlKeyword;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.Data;
import org.springframework.util.ObjectUtils;

import java.io.Serializable;
import java.util.HashMap;
import java.util.List;
import java.util.Optional;
import java.util.function.BiConsumer;

@Data
public class PageDto<T> implements Serializable {

    private Integer page = 1;

    private Integer size = 10;

    private Integer pages = 1;

    List<Object> records = null;

    private String orderBy;

    private HashMap<String, Query> query = new HashMap<>();

    private boolean asc = true;


    static HashMap<SqlKeyword, BiConsumer<QueryWrapper<?>, Query>> map = new HashMap<>();

    static {
        map.put(
                SqlKeyword.EQ,
                (wrapper, query) ->
                        wrapper.eq(
                                !ObjectUtils.isEmpty(query) && !ObjectUtils.isEmpty(query.getValue()),
                                query.getKey(),
                                query.getValue()));
        map.put(
                SqlKeyword.NE,
                (wrapper, query) ->
                        wrapper.ne(
                                !ObjectUtils.isEmpty(query) && !ObjectUtils.isEmpty(query.getValue()),
                                query.getKey(),
                                query.getValue()));
        map.put(
                SqlKeyword.LIKE,
                (wrapper, query) ->
                        wrapper.like(
                                !ObjectUtils.isEmpty(query) && !ObjectUtils.isEmpty(query.getValue()),
                                query.getKey(),
                                query.getValue()));
        map.put(
                SqlKeyword.GE,
                (wrapper, query) ->
                        wrapper.ge(
                                !ObjectUtils.isEmpty(query) && !ObjectUtils.isEmpty(query.getValue()),
                                query.getKey(),
                                query.getValue()));
        map.put(
                SqlKeyword.GT,
                (wrapper, query) ->
                        wrapper.gt(
                                !ObjectUtils.isEmpty(query) && !ObjectUtils.isEmpty(query.getValue()),
                                query.getKey(),
                                query.getValue()));
        map.put(
                SqlKeyword.LT,
                (wrapper, query) ->
                        wrapper.lt(
                                !ObjectUtils.isEmpty(query) && !ObjectUtils.isEmpty(query.getValue()),
                                query.getKey(),
                                query.getValue()));
        map.put(
                SqlKeyword.LE,
                (wrapper, query) ->
                        wrapper.le(
                                !ObjectUtils.isEmpty(query) && !ObjectUtils.isEmpty(query.getValue()),
                                query.getKey(),
                                query.getValue()));

        map.put(SqlKeyword.BETWEEN, (wrapper, query) -> {
            if (query.getValue() instanceof List) {
                List<?> values = (List<?>) query.getValue();
                if (values.size() == 2) {
                    wrapper.between(query.getKey(), values.get(0), values.get(1));
                }
            }
        });

    }

    public QueryWrapper<T> toQueryWrapper() {
        QueryWrapper<T> wrapper = new QueryWrapper<>();
        query.forEach(
                (k, v) ->
                        Optional.ofNullable(map.get(v.getSqlKeyword()))
                                .filter(ObjUtil::isNotEmpty)
                                .ifPresent(c -> c.accept(wrapper, v)));
        wrapper.orderBy(ObjUtil.isNotEmpty(orderBy), asc, orderBy);
        return wrapper;
    }

    public Page<T> toPage() {
        return new Page<>(page, size);
    }

}



@Data
class Query implements Serializable {
    private String key;

    private SqlKeyword sqlKeyword;
    private Object value;
}


